#ifndef ____THREADPOOL_HPP____
#define ____THREADPOOL_HPP____

#include "Thread.hpp"
#include <queue>
#include "Cond.hpp"
#include "mutex.hpp"
#include <memory>

template <class T>
class ThreadPool
{
    static const int defaultnum;

private:
    bool IsEmpty()
    {
        return _taskq.size() == 0;
    }
    void Task()
    {
        while (true)
        {

            T _task = T();
            {
                Mutex::AutoLock _lock(_mutex);
                while (IsEmpty() && _is_running)
                {
                    _wait_threadnum++;
                    _cond.Wait(_mutex);
                    _wait_threadnum--;
                }
                if (IsEmpty() && !_is_running)
                {
                    std::cout << "线程池退出" << std::endl;
                    break;
                }

                _task = _taskq.front();
                _taskq.pop();
            }

            // 这里你提供的Task类中的operator()是带有两个参数的,这里没有传入参数
            // 自行修改,根据逻辑,是将Task的operator()参数调用,还是在调用的时候传入参数
            _task();
        }
    }

    ThreadPool(int threadnum = defaultnum)
        : _threadnum(threadnum), _is_running(false), _wait_threadnum(0)
    {
        for (int i = 0; i < _threadnum; i++)
        {
            std::string _name = "thread_";
            _name += std::to_string(i + 1);

            THREAD::Thread t(_name, [this]()
                             { this->Task(); });
            _threads.push_back(t);
        }
    }

public:
    void push(const T &_data)
    {
        if (!_is_running)
            return;
        {
            Mutex::AutoLock _lock(_mutex);
            _taskq.push(_data);
            if (_wait_threadnum > 0)
                _cond.Signal();
        }
    }

    void Start()
    {
        if (!_is_running)
            _is_running = true;
        for (auto &th : _threads)
        {
            th.start();
        }
    }

    void Stop()
    {
        if (!_is_running)
        {
            return;
        }

        _is_running = false;
        _cond.Broadcast();

        // for (auto &th : _threads)
        // {
        //     pthread_cancel(th.Gettid());
        // }
    }

    void Wait()
    {
        for (auto &th : _threads)
        {
            th.join();
        }
    }

    static ThreadPool<T> *GetInstance()
    {
        if (!instance)
        {
            {
                Mutex::AutoLock _mutex(_smutex);
                if (!instance)
                    instance = new ThreadPool<T>();
                    instance->Start();
            }
        }

        return instance;
    }

    ~ThreadPool()
    {
    }

private:
    std::queue<T> _taskq;
    std::vector<THREAD::Thread> _threads;
    Cond _cond;
    Mutex::mutex _mutex;

    int _wait_threadnum;

    int _threadnum;
    bool _is_running;
    static ThreadPool<T> *instance;
    static Mutex::mutex _smutex;
};

template <class T>
const int ThreadPool<T>::defaultnum = 4;
template <class T>
Mutex::mutex ThreadPool<T>::_smutex;

template <class T>
ThreadPool<T> *ThreadPool<T>::instance = nullptr;

#endif
